#pragma once

#include "driver/gpio.h"
#include "driver/i2c.h"
#include "bsp/esp-bsp.h"
#include "esp_log.h"
#include <stdint.h>
#include "driver/ledc.h"

#define GT911_INT_PIN GPIO_NUM_4
#define GT911_RST_PIN GPIO_NUM_11
#define WIRELESS_CHARGE_EN_PIN GPIO_NUM_15
#define I2C_MASTER_TIMEOUT_MS 1000

#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ   /*!< I2C master read */
#define ACK_CHECK_EN 1             /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0            /*!< I2C master will not check ack from slave */
#define ACK_VAL (i2c_ack_type_t)0  /*!< I2C ack value */
#define NACK_VAL (i2c_ack_type_t)1 /*!< I2C nack value */

// 以下为待移植Arduino库

enum pd_response
{
    PD_NO_RESPONSE = 0,
    PD_SUCCESS = 1,
    PD_INVALID = 3,
    PD_CMD_NOT_SUPPORTED = 4,
    PD_FAIL = 5
};

enum husb_registers
{
    REG_PD_STATUS0 = 0x00,
    REG_PD_STATUS1 = 0x01,
    REG_SRC_PDO_5V = 0x02,
    REG_SRC_PDO_9V = 0x03,
    REG_SRC_PDO_12V = 0x04,
    REG_SRC_PDO_15V = 0x05,
    REG_SRC_PDO_18V = 0x06,
    REG_SRC_PDO_20V = 0x07,
    REG_SRC_PDO = 0x08,
    REG_GO_COMMAND = 0x09
};

enum voltage_select
{
    PDO_5V = 0b0001,
    PDO_9V = 0b0010,
    PDO_12V = 0b0011,
    PDO_15V = 0b1000,
    PDO_18V = 0b1001,
    PDO_20V = 0b1010
};

struct __attribute__((packed))
{
    uint16_t ma_5V;
    uint16_t ma_9V;
    uint16_t ma_12V;
    uint16_t ma_15V;
    uint16_t ma_18V;
    uint16_t ma_20V;
} capability;

union
{
    struct
    {
        unsigned PD_SRC_CURRENT : 4;
        unsigned PD_SRC_VOLTAGE : 4;

        unsigned CURRENT_5V : 2;
        unsigned VOLTAGE_5V : 1;
        unsigned PD_RESPONSE : 3;
        unsigned ATTACH : 1;
        unsigned CC_DIR : 1;
    };

    struct
    {
        uint8_t PD_STATUS0;
        uint8_t PD_STATUS1;
    };

    uint16_t combined;

} status;
/**
 * @brief Get the capabilities of the PSU
 * @return uint64_t The capabilities of the PSU
 * @note The capabilities are packed into a 64 bit integer, with each byte representing a different capability
 */
uint64_t get_capabilities();
void set_voltage(voltage_select voltage);
esp_err_t update_pd_status();
uint8_t get_pd_voltage();
uint16_t get_pd_current();
void initHUSB238();
void initHUSB238Daemon();
void initFan();
void setFanSpeedPercentage(uint8_t percentage);

/**
 * @brief Read a byte from the i2c register
 * @param reg The register to read from
 * @param data The data read from the register
 * @return esp_err_t ESP_OK if successful, ESP_FAIL otherwise
 */
static esp_err_t __readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t nBytesRead = 1);
/**
 * @brief Write a byte to the i2c register
 * @param reg The register to write to
 * @param data The data to write to the register
 * @return esp_err_t ESP_OK if successful, ESP_FAIL otherwise
 */
static esp_err_t __writeRegister(uint8_t address, uint8_t reg, uint8_t data);
const uint8_t m_i2c_address = 0x08;
const uint8_t m_capability_reg_count = 6;
const uint16_t m_src_current[16] = {
    500,
    700,
    1000,
    1250,
    1500,
    1750,
    2000,
    2250,
    2500,
    2750,
    3000,
    3250,
    3500,
    4000,
    4500,
    5000};
const uint8_t m_src_voltage[7] = {
    0,
    5,
    9,
    12,
    15,
    18,
    20};
const uint16_t m_apple_current[4] = {
    500,
    1500,
    2400,
    3000};

extern SemaphoreHandle_t __i2c_mutex;